package com.hxs.email.client;

import com.alibaba.fastjson.JSON;

import com.hxs.email.pojo.entity.ScoreItem;
import com.hxs.email.pojo.response.ScorePageResponse;
import com.hxs.email.result.Result;
import com.hxs.email.util.PasswordEncryptionUtil;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.http.client.CookieStore;
import org.json.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.springframework.stereotype.Component;


import java.io.IOException;

import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
@Setter
@Component
public class EduClient {
    /**
     * 教务系统地址 本地址为河北师大教务地址 请根据自己学校进行修改
     */
    private final String baseUrl = "http://jwgl.hebtu.edu.cn";
    private final int timeout = 10;
    private String keyUrl;
    private String loginUrl;
    private CloseableHttpClient httpClient;
    private CookieStore cookieStore;
    private Map<String, String> cookies;
    private Map<String, String> headers;

    public EduClient(Map<String, String> cookies) {
        // 基础配置

        try {
            this.keyUrl = new URI(baseUrl).resolve("xtgl/login_getPublicKey.html").toString();
            this.loginUrl = new URI(baseUrl).resolve("xtgl/login_slogin.html").toString();
        } catch (URISyntaxException e) {
            throw new RuntimeException("Invalid base URL", e);
        }

        // 设置常见请求头防止403
        this.headers = new HashMap<>();
        headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
        headers.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
        headers.put("Accept-Language", "zh-CN,zh;q=0.9");
        headers.put("Connection", "keep-alive");
        headers.put("Cache-Control", "max-age=0");
        headers.put("Upgrade-Insecure-Requests", "1");
        headers.put("Host", "jwgl.hebtu.edu.cn");



        // 初始化HTTP客户端
        this.cookieStore = new BasicCookieStore();
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(timeout * 1000)
                .setSocketTimeout(timeout * 1000)
                .build();

        this.httpClient = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig)
                .setRedirectStrategy(new LaxRedirectStrategy())
                .setDefaultCookieStore(cookieStore)
                .build();

        this.cookies = cookies;
    }



    /**
     * 登录并返回cookie
     * 请求方式 POST
     * 请求参数 sid, password
     * Cookie no
     *
     * @param sid
     * @param password
     * @return
     */

    public Result<Map<String, String>> login(String sid, String password) {
        try {
            // 登录页
            HttpGet reqCsrf = new HttpGet(loginUrl);
            //headers.forEach(reqCsrf::setHeader);

            try (CloseableHttpResponse response = httpClient.execute(reqCsrf)) {
                if (response.getStatusLine().getStatusCode() != 200) {
                    return Result.error("登录失败");
                }

                String responseBody = EntityUtils.toString(response.getEntity());
                Document doc = Jsoup.parse(responseBody);

                // 获取csrf_token
                Element csrfElement = doc.selectFirst("#csrftoken");
                String csrfToken = csrfElement != null ? csrfElement.attr("value") : "";

                // 获取cookies
                Map<String, String> preCookies = new HashMap<>();
                cookieStore.getCookies().forEach(cookie ->
                        preCookies.put(cookie.getName(), cookie.getValue())
                );

                // 获取publicKey并加密密码
                HttpGet reqPubkey = new HttpGet(keyUrl);


                try (CloseableHttpResponse pubkeyResponse = httpClient.execute(reqPubkey)) {
                    String pubkeyBody = EntityUtils.toString(pubkeyResponse.getEntity());
                    JSONObject pubkeyJson = new JSONObject(pubkeyBody);
                    String modulus = pubkeyJson.getString("modulus");
                    String exponent = pubkeyJson.getString("exponent");
                    // 不需要验证码
                    String encryptPassword = PasswordEncryptionUtil.encryptPassword(password, modulus, exponent);

                    // 登录数据
                    List<BasicNameValuePair> formData = new ArrayList<>();
                    formData.add(new BasicNameValuePair("csrftoken", csrfToken));
                    formData.add(new BasicNameValuePair("yhm", sid));
                    formData.add(new BasicNameValuePair("mm", encryptPassword));

                    // 请求登录
                    HttpPost reqLogin = new HttpPost(loginUrl);
                    //headers.forEach(reqLogin::setHeader);
                    reqLogin.setEntity(new UrlEncodedFormEntity(formData, "UTF-8"));

                    try (CloseableHttpResponse loginResponse = httpClient.execute(reqLogin)) {
                        String loginBody = EntityUtils.toString(loginResponse.getEntity());
                        Document loginDoc = Jsoup.parse(loginBody);
                        Element tipsElement = loginDoc.selectFirst("p#tips");

                        if (tipsElement != null) {
                            String tipsText = tipsElement.text();
                            if (tipsText.contains("用户名或密码")) {
                                log.info("用户名或密码不正确");
                                throw new RuntimeException("用户名或密码错误");
                            }
                            return Result.error(tipsText);
                        }

                        // 获取cookies
                        Map<String, String> newCookies = new HashMap<>();
                        cookieStore.getCookies().forEach(cookie ->
                                newCookies.put(cookie.getName(), cookie.getValue())
                        );
                        this.cookies = newCookies;

                        return Result.success(cookies);
                    }
                }
            }
        } catch (IOException e) {
            log.error("登录超时 {}", e.getMessage());
            return Result.error("登录超时");
        } catch (Exception e) {
            log.error("登录错误: {}", e.getMessage());
            return Result.error("登录错误");
        }
    }



    /**
     * 获取学生成绩
     * 请求方式：GET
     * Cookie yes
     *
     * @return
     */
    public List<ScoreItem>  getStudentScore(Integer term,Integer year) {
        try {


            URI scoreURL = new URI(baseUrl).resolve("/cjcx/cjcx_cxXsgrcj.html?doType=query&gnmkdm=N305005");
            HttpPost httpPost = new HttpPost(scoreURL);
            httpPost.setHeader("Cookie", getCookieString());

            List<BasicNameValuePair> formData = new ArrayList<>();
            formData.add(new BasicNameValuePair("xnm", year.toString()));
            formData.add(new BasicNameValuePair("xqm", term.toString()));
            formData.add(new BasicNameValuePair("sfzgcj", ""));
            formData.add(new BasicNameValuePair("queryModel.showCount", "200"));
            formData.add(new BasicNameValuePair("queryModel.currentPage", "1"));


            httpPost.setEntity(new UrlEncodedFormEntity(formData, StandardCharsets.UTF_8));

            CloseableHttpResponse response = httpClient.execute(httpPost);
            if (response.getStatusLine().getStatusCode() != 200) {
                throw new RuntimeException("Login failed");
            }
            String responseBody = EntityUtils.toString(response.getEntity());
            checkLogin(responseBody);


            ScorePageResponse scorePageResponse = JSON.parseObject(responseBody, ScorePageResponse.class);
            log.info("成绩获取成功 {}", scorePageResponse);

            //只返回成绩列表
            return scorePageResponse.getItems();

        } catch (URISyntaxException | IOException e) {
            throw new RuntimeException("获取学生成绩失败");
        }
    }



    /**
     * 获取cookie字符串
     * @return
     */
    private String getCookieString() {
        if (this.cookies == null) {
            throw new RuntimeException("未登录");
        }
        return this.cookies.entrySet().stream()
                .map(entry -> entry.getKey() + "=" + entry.getValue())
                .collect(Collectors.joining("; "));
    }


    /**
     * 检查登录状态
     */
    private void checkLogin(String responseBody){
        Document doc = Jsoup.parse(responseBody);
        Element h5Element = doc.selectFirst("h5");
        Element title = doc.selectFirst("title");
        if (h5Element != null && h5Element.text().contains("用户登录")||title != null && title.text().contains("身份")) {
            log.info("用户未登录");
            throw new RuntimeException("用户未登录");
        }
    }

    private List<String> extractNumbers(String text) {
        // 创建正则表达式匹配模式
        Pattern pattern = Pattern.compile("\\d+");
        Matcher matcher = pattern.matcher(text);

        // 提取所有匹配的数字
        List<String> numbers = new ArrayList<>();
        while (matcher.find()) {
            numbers.add(matcher.group());
        }

        return numbers;
    }

}